package com.gmrz.uaf.protocol.v1.processor;

import com.gmrz.uaf.common.GuiceUtil;
import com.gmrz.uaf.db.DAOException;
import com.gmrz.uaf.policy.verification.StepupPolicyProcessor;
import com.gmrz.uaf.protocol.v1.json.UAFSchemaBuilder;
import com.gmrz.uaf.protocol.v1.processor.exception.PolicyNotFoundException;
import com.gmrz.uaf.protocol.v1.processor.exception.UAFErrorCode;
import com.gmrz.uaf.protocol.v1.schema.Authenticator;
import com.gmrz.uaf.protocol.v1.schema.MatchCriteria;
import com.gmrz.uaf.protocol.v1.schema.Policy;
import com.gmrz.uaf.protocol.v1.schema.RegistrationRequest;
import com.gmrz.uas.plugin.exception.PluginException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class UAFRegInitProcessor extends UAFBaseProcessor {
	private static final Logger LOG = LogManager.getLogger(UAFRegInitProcessor.class);

	public List<RegistrationRequest> request(String plainUserName,String hashUserName,String appID,String deviceID,
                                             String authType,String transType,byte[] challengeParam,String dn)
			throws PolicyNotFoundException, DAOException, PluginException {
		RegistrationRequest request = GuiceUtil.getProcessorInjector()
				.getInstance(RegistrationRequest.class);
        // 根据认证方式、appid、业务类型查询策略，策略是通过管理系统提前配置好的
		Policy p = this.policyManager.getNamedPolicy(authType,appID,transType);
		LOG.info("Policy:" + UAFSchemaBuilder.getGson().toJson(p));
		// 如果策略不存在则抛出异常
		if (p == null) {
			LOG.error("Requested policy {} is not available on server", "POLICY_"+appID+"_"+authType);
			throw new PolicyNotFoundException(UAFErrorCode.BIZ_POLICY_NOT_FOUND);
		}
		// 根据当前用户名等信息获取已经注册的认证数据（aaid、keyid）
		List<MatchCriteria> mcList = getMCListForAlreadyRegistered(hashUserName,appID,deviceID,authType,transType);
		if (mcList != null) {
			p.appendDisallowed(mcList);
		}
		// 生成挑战值
		byte[] challenge = getRandom(32);
		challenge = ArrayUtils.addAll(challenge,challengeParam);
		request.getHeader().getServerData().withChallenge(challenge)
				.withPolicyName(p.getPolicyName()).withUserName(plainUserName);
		request.getHeader().setApplicationID(this.getServerConfig().getApplicationID(appID,transType));

		request.getChallenge().setChallenge(challenge);
		request.setPolicy(p);
		request.setUsername(hashUserName+"_"+authType+"_"+transType);
		if(serverConfig.getAppIdUrlBoolean(appID,transType)) {
			setFacetsAaid(request, appID);
		}
		List<RegistrationRequest> requests = new ArrayList<RegistrationRequest>();
		requests.add(request);
		return requests;
	}

	protected List<MatchCriteria> getMCListForAlreadyRegistered(String username,String appID,String deviceID,
															  String authType,String transType) throws DAOException {
		Set<Authenticator> registeredList = getAuthenticatorListForAlreadyRegistered(username,appID,
				deviceID,authType,transType);
		return StepupPolicyProcessor.convertAuthenticatorsToMCs(registeredList);
	}

	protected List<MatchCriteria> getMCListForAlreadyRegisteredNoDeviceId(String username,String appID,
																String authType,String transType) throws DAOException {
		Set<Authenticator> registeredList = getAuthenticatorListForAlreadyRegisteredNoDeviceId(username,appID,
				authType,transType);
		return StepupPolicyProcessor.convertAuthenticatorsToMCs(registeredList);
	}


}
